
from dataclasses import dataclass
from datetime import datetime
from wsgiref.handlers import format_date_time
from time import mktime
import hashlib
import base64
import hmac
from urllib.parse import urlencode
import json
import requests
from io import BytesIO, BufferedReader


@dataclass
class OCRConfig:
    app_id: str
    api_key: str
    api_secret: str
    base_url: str = "https://api.xf-yun.com/v1/private/sf8e6aca1"


class AssembleHeaderException(Exception):
    def __init__(self, msg):
        self.message = msg


class Url:
    def __init__(self, host, path, schema):
        self.host = host
        self.path = path
        self.schema = schema
        pass


class OCRServer:
    config: OCRConfig = None

    @staticmethod
    def sha256base64(data):
        sha256 = hashlib.sha256()
        sha256.update(data)
        digest = base64.b64encode(sha256.digest()).decode(encoding='utf-8')
        return digest

    @staticmethod
    def parse_url(requset_url):
        stidx = requset_url.index("://")
        host = requset_url[stidx + 3:]
        schema = requset_url[:stidx + 3]
        edidx = host.index("/")
        if edidx <= 0:
            raise AssembleHeaderException("invalid request url:" + requset_url)
        path = host[edidx:]
        host = host[:edidx]
        u = Url(host, path, schema)
        return u

    # build websocket auth request url
    @staticmethod
    def assemble_ws_auth_url(method="POST", api_key="", api_secret=""):
        u = OCRServer.parse_url(OCRServer.config.base_url)
        host = u.host
        path = u.path
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))
        print(date)
        # date = "Thu, 12 Dec 2019 01:57:27 GMT"
        signature_origin = "host: {}\ndate: {}\n{} {} HTTP/1.1".format(
            host, date, method, path)
        print(signature_origin)
        signature_sha = hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
                                 digestmod=hashlib.sha256).digest()
        signature_sha = base64.b64encode(
            signature_sha).decode(encoding='utf-8')
        authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (
            api_key, "hmac-sha256", "host date request-line", signature_sha)
        authorization = base64.b64encode(
            authorization_origin.encode('utf-8')).decode(encoding='utf-8')
        print(authorization_origin)
        values = {
            "host": host,
            "date": date,
            "authorization": authorization
        }

        return OCRServer.config.base_url + "?" + urlencode(values)

    @classmethod
    def _get_body(cls,file: BufferedReader,file_type:str):
        file.seek(0)
        imageBytes = file.read()
        body = {
            "header": {
                "app_id": cls.config.app_id,
                "status": 3
            },
            "parameter": {
                "sf8e6aca1": {
                    "category": "ch_en_public_cloud",
                    "result": {
                        "encoding": "utf8",
                        "compress": "raw",
                        "format": "json"
                    }
                }
            },
            "payload": {
                "sf8e6aca1_data_1": {
                    "encoding": file_type,
                    "image": str(base64.b64encode(imageBytes), 'UTF-8'),
                    "status": 3
                }
            }
        }
        return body

    @staticmethod
    def reconizie(file: BufferedReader,file_type:str="jpg"):
        url = OCRServer.assemble_ws_auth_url(
            api_key=OCRServer.config.api_key, api_secret=OCRServer.config.api_secret)
        headers = {'content-type': "application/json",
                   'host': 'api.xf-yun.com', 'app_id': OCRServer.config.app_id}
        body = OCRServer._get_body(file,file_type)
        response = requests.post(
            url, data=json.dumps(body), headers=headers)
        result = json.loads(response.content.decode())
        finalResult = base64.b64decode(result["payload"]["result"]["text"]).decode()
        finalResult = finalResult.replace(" ", "").replace("\n", "").replace("\t", "").strip()
        return finalResult


if __name__ == '__main__':
    config = OCRConfig(
        app_id="f4b3bfd8",
        api_key="3f6b034a6397fab4d4478345f42340e2",
        api_secret="MDdhM2I3NjM0NjViOTVlY2JkZjQ5NTZj"
    )

    OCRServer.config = config
    file = open("/home/loby/图片/微信图片_2025-04-14_114838_098.png", "rb")
    result = OCRServer.reconizie(file,"png")
    print(result)